/*
 *  Copright: 2008 Philipp Leitner, Distributed Systems Group,
 *            TU Wien, leitner@infosys.tuwien.ac.at
 *
 *  This file is part of DAIOS.
 *
 *  DAIOS is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as
 *  published by the Free Software Foundation.
 * 
 *  DAIOS is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with DAIOS.  If not, see
 *  <http://www.gnu.org/licenses/>.
 * 
 */

package at.ac.tuwien.infosys.dsg.daios.wsdl.matcher;

import at.ac.tuwien.infosys.dsg.daios.exceptions.AmbigiousException;
import at.ac.tuwien.infosys.dsg.daios.framework.structs.DaiosInputMessage;
import at.ac.tuwien.infosys.dsg.daios.wsdl.interfaces.IWSDL;
import at.ac.tuwien.infosys.dsg.daios.wsdl.interfaces.IWSDLMessage;
import at.ac.tuwien.infosys.dsg.daios.wsdl.interfaces.IWSDLOperation;

/**
 * This is a special class that wraps much of the logics of
 * the SOAP part of the Daios framework. It implements the
 * 'matching' between
 * the information provided in Daios messages and the WSDL
 * definitions.
 * 
 * <p>
 * 
 * All invokers should use this matcher to get missing
 * information, i.e. information that is not provided by
 * the user.
 * 
 * @author philipp
 *
 */
public class WSDLStructuralMatcher {
	
	// the wsdl definition against which
	// this matcher should compare
	private IWSDL wsdl = null;
	
	// the matcher instance used
	private Matcher matcher = null;
	
	/**
	 * Constructs a new matcher. Takes a parsed
	 * WSDL definition in Daios format.
	 * 
	 * @param wsdl The definitions in Daios
	 * format.
	 */
	public WSDLStructuralMatcher(IWSDL wsdl) {
		this.wsdl = wsdl;
		matcher = WSDLStyleMapper.get(wsdl.getBindingStyle());
	}
	
	/**
	 * Guess an endpoint address from the definitions.
	 * 
	 * <p>
	 * 
	 * This works only if there is exactly one service
	 * with exactly one port, which has a SOAP address
	 * extensibility element. This is not such a hard
	 * constraint since most services are set up that way.
	 * 
	 * <p>
	 * 
	 * If this method throws an AmbigiousException the
	 * endpoint has to be set explicitly prior to invoking.
	 * 
	 * @return The endpoint address as String.
	 * 
	 * @throws AmbigiousException
	 */
	public String getEndpoint() throws AmbigiousException {
		
		return matcher.getEndpoint(wsdl);
		
	}
	
	/**
	 * Get the WSDL message that is most similar to a given
	 * Daios input message.
	 * 
	 * @param input The Daios input message.
	 * @return The WSDL message that has the lowest distance to
	 * the given input message.
	 * @throws AmbigiousException Thrown to indicate that 2 or
	 * more messages in the definition are bound for the lowest
	 * distance to the input, or that no message is at all
	 * similar to the provided input.
	 * 
	 */	
	public IWSDLMessage getSimilarMsg(DaiosInputMessage input)
		throws AmbigiousException {
		
		return matcher.getSimilarMsg(wsdl, input);
		
	}

	/**
	 * Check if a given WSDL message is a possible input message for our
	 * definition, and if the given Daios message can be converted into
	 * such a WSDL message.
	 * 
	 * @param msgToUse The WSDL message to check.
	 * @param message The Daios message to check against.
	 * 
	 * @throws AmbigiousException If the WSDL message is not compliant.
	 */
	public void checkCompliance(IWSDLMessage msgToUse, DaiosInputMessage message)
		throws AmbigiousException {
		
		matcher.checkCompliance(wsdl, msgToUse, message);
	
	}

	/**
	 * Get a WSDL operation that has a given WSDL message
	 * as input. Operations that take this message as
	 * output or fault message will not be considered.
	 * 
	 * <p>
	 * 
	 * This method fails with an AmbigiousException if there
	 * is more than one operation in the WSDL definition that
	 * takes this message as input.
	 * 
	 * @param msgToUse The message.
	 * @return The operation that takes msg as input.
	 * 
	 * @throws AmbigiousException
	 */
	public IWSDLOperation getOperation(IWSDLMessage msgToUse) throws AmbigiousException {
		return matcher.getOperation(wsdl, msgToUse);
	}
	
}
